package com.ruoyi.iot.exchange;

import com.ruoyi.iot.domain.IotFrame;
import com.ruoyi.iot.domain.vo.ProjectVO;
import com.ruoyi.iot.domain.vo.exchange.ProjectFrameDTO;
import com.ruoyi.iot.exchange.network.tcp.TcpNetty;
import com.ruoyi.iot.exchange.network.tcp.cache.TcpChannelCache;
import com.ruoyi.iot.exchange.network.tcp.handler.TCPDispatchHandlerFactory;
import com.ruoyi.iot.exchange.network.tcp.handler.TCPDispatchHandlerGatherProxy;
import com.ruoyi.iot.exchange.network.tcp.handler.dispatch.TCPDispatchHandler;
import com.ruoyi.iot.exchange.redis.RedisProductCache;
import com.ruoyi.iot.feign.IExchangeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

@RestController
@RequestMapping
@Slf4j
public class IotExchangeServiceImpl implements IExchangeService {

    /**
     * netty保存产品id，和task任务的接口
     */
    ConcurrentHashMap<Long, TcpNetty> nettyTask = new ConcurrentHashMap<>();

    /**
     * 服务池
     */
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(8);

    @Autowired
    RedisProductCache redisProductCache;


    @Override
    public Boolean devOnline(String devNum) {

        Boolean rst = TcpChannelCache.getChannel(devNum) != null;

        return rst;
    }

    @Override
    public void startProjectServer(ProjectFrameDTO projectFrameDTO) {

        TcpNetty tcpNetty = nettyTask.get(projectFrameDTO.getProjectId());
        if(tcpNetty != null) {
          log.info(String.format("product:name=>%s running!", projectFrameDTO.getProjectName()));
          return;
        }

        TCPDispatchHandlerGatherProxy tcpDispatchHandlerGatherProxy = new TCPDispatchHandlerGatherProxy();
        List<IotFrame> frameDTOs = projectFrameDTO.getFrames();
        frameDTOs.forEach(frame -> {
            TCPDispatchHandler tcpDispatchHandler = TCPDispatchHandlerFactory.create(frame);
            if(tcpDispatchHandler == null) {
                log.info("null handler type:" + frame.getType());
            }
            log.info("handler:" + tcpDispatchHandler.getClass().getSimpleName());
            tcpDispatchHandlerGatherProxy.addHandler(tcpDispatchHandler);
        });
        tcpNetty = new TcpNetty( projectFrameDTO.getTransport().intValue(), tcpDispatchHandlerGatherProxy);
        nettyTask.put(projectFrameDTO.getProjectId(), tcpNetty);
        executorService.execute(tcpNetty);
        log.info(String.format("product:id=>%s name=>%s start!", projectFrameDTO.getProjectId(),
                projectFrameDTO.getProjectName()));
        redisProductCache.saveProjectServer(projectFrameDTO);


    }

    @Override
    public void stopProductServer(ProjectVO projectVO) {
        Long projectId = projectVO.getProjectId();
        TcpNetty tcpNetty = nettyTask.get(projectId);

        if (tcpNetty != null) {
            tcpNetty.cancel();
            redisProductCache.removeProjectServer(projectId);
            nettyTask.remove(projectId);
            log.info(String.format("product id: %s stop!",projectId));
        }
    }




    @PostConstruct
    public void restartProjectServer() {
        redisProductCache.getProjectServer().forEach(item -> {
            startProjectServer(item);
        });
    }





}
